﻿using Maplatform;
using Maplatform.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using Umbraco.Web.Editors;
using Umbraco.Web.Mvc;
using UmbracoExtending.Dealer.Model;
using UmbracoExtending.Dealer.Model.Dealer;
using UmbracoExtending.Dealer.Model.Config;
using UmbracoExtending.Dealer.Model.District;
using Umbraco.Core.Persistence;

namespace UmbracoExtending.Dealer.Controller
{
    /// <summary>
    /// 经销商后端控制器
    /// </summary>
    [PluginController("UmbracoDealer")]
    public class BackendDealerController : UmbracoAuthorizedJsonController
    {
        /// <summary>
        /// 创建经销商
        /// </summary>
        /// <param name="dealer">前端传递的经销商对象</param>
        /// <returns>返回标识对象，包含同步路径</returns>
        [HttpPost]
        public ErrorResultExtend<List<string>> Create(DealerItem dealer)
        {
            var db = UmbracoContext.Application.DatabaseContext.Database;
            var er = new ErrorResultExtend<List<string>>() { ErrorCode = -1, ErrorMsg = "系统错误", Extend = new List<string>() { "-1" } };
            var config = this.GetConfig();
            var geo = this.GeocoderAddress(config, dealer.Address, "");
            if (geo.Status == 0)
            {
                dealer.Province = geo.AddressComponents.Province;
                dealer.City = geo.AddressComponents.City;
                dealer.District = geo.AddressComponents.District;
                dealer.Lat = geo.Location.Lat;
                dealer.Lng = geo.Location.Lng;
                dealer.IsMistake = "n";
                try
                {
                    var r = db.Insert("umbracoExtendingDealer", "Id", true, dealer);
                    er.ErrorCode = 0;

                    er.Extend = this.GetPath(config, dealer.Id);

                    er.ErrorMsg = "保存成功!";
                }
                catch (Exception e)
                {
                    Logger.Error(this.GetType(), "保存经销商时发生错误", e);
                    er.ErrorMsg = "数据库保存错误";
                }
            }
            else
            {
                er.ErrorMsg = "地址解析错误，请输入更详细的地址";
            }
            return er;
        }

        /// <summary>
        /// 根据编号获取经销商信息
        /// </summary>
        /// <param name="id">编号</param>
        /// <returns>返回经销商对象，包含路径信息</returns>
        [HttpGet]
        public DealerItemExtend Get(int id)
        {
            var db = UmbracoContext.Application.DatabaseContext.Database;
            var query = new Sql().Select("Id, Province, City, District, Address, StoreName, ResponsiblePerson, ContactNumber, Lat, Lng, IsMistake")
                .From("[umbracoExtendingDealer]")
                .Where("Id = @0", id);
            var result = db.FirstOrDefault<DealerItemExtend>(query);
            if (null != result)
            {   
                var config = this.GetConfig();
                result.Path = this.GetPath(config, id);
                return result;
            }
            return new DealerItemExtend();
        }

        /// <summary>
        /// 分页查询经销商数据
        /// </summary>
        /// <param name="key">查询密钥</param>
        /// <param name="index">页码</param>
        /// <param name="size">每页数</param>
        /// <param name="keyword">搜索关键词</param>
        /// <returns>返回搜索到的列表对象</returns>
        [HttpGet]
        public DealerList FindAll(string key, int index, int size, string keyword)
        {
            index = (index <= 0) ? 1 : index;
            size = (size <= 0) ? 20 : size;

            DealerList result = new DealerList() { CurrentPage = index };

            var db = UmbracoContext.Application.DatabaseContext.Database;
            string[] param = key.Split('_');
            string code = param[0].Substring(0, 1).ToUpper() + param[0].Substring(1) + "Code";
            var q1 = new Sql().Select("COUNT(*)").From("[V_umbracoExtendingDealer]").Where(code + " = @0", param[1]);
            result.Total = db.ExecuteScalar<int>(q1);
            if ((result.Total % size) > 0)
            {
                result.PageCount = (result.Total - result.Total % size) / size + 1;
            }
            else
            {
                result.PageCount = result.Total / size;
            }

            var config = this.GetConfig();
            result.Path = this.GetPath(config, param[1]);

            var query = new Sql().Select("Id, Province, City, District, Address, StoreName, ResponsiblePerson, ContactNumber, Lat, Lng, IsMistake")
                .From("[V_umbracoExtendingDealer]")
                .Where(code + " = @0", param[1]);
            var dealers = db.Page<DealerItem>(index, size, query.OrderByDescending("Id")).Items;
            result.Dealers = dealers;

            return result;
        }

        /// <summary>
        /// 修改经销商信息
        /// </summary>
        /// <param name="dealer">前端传入的经销商对象</param>
        /// <returns>返回带路径的经销商对象</returns>
        [HttpPut]
        public ErrorResultExtend<List<string>> Put(DealerItem dealer)
        {
            var db = UmbracoContext.Application.DatabaseContext.Database;
            var result = new ErrorResultExtend<List<string>>() { ErrorCode = -1, ErrorMsg = "系统错误", Extend = new List<string>() };

            var query = new Sql().Select("Id, Province, City, District, Address, StoreName, ResponsiblePerson, ContactNumber, Lat, Lng, IsMistake")
                .From("[umbracoExtendingDealer]")
                .Where("Id = @0", dealer.Id);

            var origin = db.FirstOrDefault<DealerItem>(query);
            var config = this.GetConfig();
            if (origin.IsMistake.Equals("y") || !origin.Address.Equals(dealer.Address))
            {
                var geo = this.GeocoderAddress(config, dealer.Address, "");
                if (geo.Status == 0)
                {
                    origin.Address = dealer.Address;
                    origin.Province = geo.AddressComponents.Province;
                    origin.City = geo.AddressComponents.City;
                    origin.District = geo.AddressComponents.District;
                    origin.Lat = geo.Location.Lat;
                    origin.Lng = geo.Location.Lng;
                    origin.IsMistake = "n";
                }
                else
                {
                    result.ErrorMsg = "地址解析错误，请重新输入";
                    return result;
                }
            }
            origin.StoreName = dealer.StoreName;
            origin.ResponsiblePerson = dealer.ResponsiblePerson;
            origin.ContactNumber = dealer.ContactNumber;

            try
            {
                int row = db.Update("umbracoExtendingDealer", "Id",
                    new
                    {
                        origin.Province,
                        origin.City,
                        origin.District,
                        origin.Address,
                        origin.StoreName,
                        origin.ResponsiblePerson,
                        origin.ContactNumber,
                        origin.Lat,
                        origin.Lng,
                        origin.IsMistake
                    },
                    dealer.Id);
                if (row > 0)
                {
                    result.ErrorCode = 0;
                    result.Extend = this.GetPath(config, dealer.Id);
                    result.ErrorMsg = "保存成功!";
                }
                else
                {
                    result.ErrorMsg = "地址解析错误，请重新输入";
                }
            }
            catch (Exception e)
            {
                Logger.Error(this.GetType(), "保存经销商时发生错误", e);
                result.ErrorMsg = "数据库保存错误";
            }
            return result;
        }

        /// <summary>
        /// 地址解析接口
        /// </summary>
        /// <param name="dealer">要重新解析的经销商对象</param>
        /// <returns>返回标识码</returns>
        [HttpPut]
        public ErrorResult Geocoder(DealerItem dealer)
        {
            var db = UmbracoContext.Application.DatabaseContext.Database;
            var result = new ErrorResult() { ErrorCode = -1, ErrorMsg = "系统错误" };

            var query = new Sql().Select("Id, Province, City, District, Address, StoreName, ResponsiblePerson, ContactNumber, Lat, Lng, IsMistake")
                .From("[umbracoExtendingDealer]")
                .Where("Id = @0", dealer.Id);

            var origin = db.FirstOrDefault<DealerItem>(query);
            var config = this.GetConfig();

            var geo = this.GeocoderAddress(config, origin.Address, "");

            if (geo.Status == 0)
            {
                origin.Address = origin.Address;
                origin.Province = geo.AddressComponents.Province;
                origin.City = geo.AddressComponents.City;
                origin.District = geo.AddressComponents.District;
                origin.Lat = geo.Location.Lat;
                origin.Lng = geo.Location.Lng;
                origin.IsMistake = "n";

                try
                {
                    int row = db.Update("umbracoExtendingDealer", "Id",
                        new
                        {
                            origin.Province,
                            origin.City,
                            origin.District,
                            origin.Address,
                            origin.StoreName,
                            origin.ResponsiblePerson,
                            origin.ContactNumber,
                            origin.Lat,
                            origin.Lng,
                            origin.IsMistake
                        },
                        dealer.Id);
                    if (row > 0)
                    {
                        result.ErrorCode = 0;
                        result.ErrorMsg = "保存成功!";
                    }
                    else
                    {
                        result.ErrorMsg = "地址解析错误，请重新输入";
                    }
                }
                catch (Exception e)
                {
                    Logger.Error(this.GetType(), "保存经销商时发生错误", e);
                    result.ErrorMsg = "数据库保存错误";
                }
            }
            else
            {
                result.ErrorMsg = "地址解析错误，请重新输入";
                return result;
            }            
            return result;
        }


        /// <summary>
        /// 删除经销商接口
        /// </summary>
        /// <param name="key">删除key</param>
        /// <returns>返回标识码</returns>
        [HttpDelete]
        public ErrorResult Delete(string key)
        {
            var db = UmbracoContext.Application.DatabaseContext.Database;
            var result = new ErrorResult() { ErrorCode = -1, ErrorMsg = "删除失败" };
            if (key.StartsWith("dealer_"))
            {
                string id = key.Split('_')[1];
                if (db.Execute("DELETE FROM [umbracoExtendingDealer] WHERE [Id] = @0", id) > 0)
                {
                    result.ErrorCode = 0;
                    result.ErrorMsg = "删除成功";
                }
            }
            else
            {
                string[] param = key.Split('_');
                string columnName = param[0].Substring(0, 1).ToUpper() + param[0].Substring(1) + "Code";
                if (db.Execute("DELETE FROM [umbracoExtendingDealer] WHERE Id IN (SELECT Id FROM [V_umbracoExtendingDealer] WHERE " + columnName + " = @0)", param[1]) > 0)
                {  
                    result.ErrorCode = 0;
                    result.ErrorMsg = "删除成功";
                }
            }

            return result;
        }


        /***************************************************************************************
         * 
         ******************************* 分割线，下面是私有方法 *******************************
         * 
         **************************************************************************************/

        /// <summary>
        /// 获取配置项
        /// </summary>
        /// <returns>返回默认的配置项</returns>
        private DealerConfiguration GetConfig()
        {
            var db = UmbracoContext.Application.DatabaseContext.Database;
            var query = new Sql().Select("Id, MapPlatform, MapAppKey, ListView, ShowWarning, SimpleMode, ShowTwoLayers")
                .From("[umbracoExtendingDealerConfig]");
            return db.FirstOrDefault<DealerConfiguration>(query);
        }

        /// <summary>
        /// 根据经销商编号返回路径
        /// </summary>
        /// <param name="config">配置</param>
        /// <param name="dealerId">经销商编号</param>
        /// <returns>返回路径数组</returns>
        private List<string> GetPath(DealerConfiguration config, int dealerId)
        {
            List<string> result = new List<string>() { "-1" };
            var district = this.GetDistrictByDealer(dealerId);

            if (null != district)
            {
                result.Add("province_" + district.ProvinceCode);

                if (config.SimpleMode.Equals("y"))
                {
                    if (LocalConfiguration.MunicipalityCode.IndexOf(district.ProvinceCode) >= 0)
                    {
                        result.Add("district_" + district.DistrictCode);
                    }
                    else
                    {
                        result.Add("city_" + district.CityCode);
                    }
                }
                else
                {
                    result.Add("city_" + district.CityCode);
                    result.Add("district_" + district.DistrictCode);
                }

                if (config.ListView.Equals("n"))
                {
                    result.Add("dealer_" + dealerId);
                }
            }

            return result;
        }

        /// <summary>
        /// 根据区县编码获取路径
        /// </summary>
        /// <param name="config">配置项</param>
        /// <param name="districtCode">区县编码</param>
        /// <returns>返回路径</returns>
        private List<string> GetPath(DealerConfiguration config, string districtCode)
        {
            List<string> result = new List<string>() { "-1" };
            var district = this.GetDistrict(districtCode);

            if (null != district)
            {
                result.Add("province_" + district.ProvinceCode);

                if (config.SimpleMode.Equals("y"))
                {
                    if (LocalConfiguration.MunicipalityCode.IndexOf(district.ProvinceCode) >= 0)
                    {
                        result.Add("district_" + district.DistrictCode);
                    }
                    else
                    {
                        result.Add("city_" + district.DistrictCode);
                    }
                }
                else
                {
                    result.Add("city_" + district.CityCode);
                    result.Add("district_" + district.DistrictCode);
                }
            }
            return result;
        }

        /// <summary>
        /// 根据经销商编号获取区域信息
        /// </summary>
        /// <param name="dealerId">经销商编号</param>
        /// <returns></returns>
        private DistrictItem GetDistrictByDealer(int dealerId)
        {
            var db = UmbracoContext.Application.DatabaseContext.Database;
            var query = new Sql().Select("ProvinceCode, ProvinceName, CityCode, CityName, DistrictCode, DistrictName, AliasName")
                .From("[V_umbracoExtendingDealer]")
                .Where("Id = @0", dealerId);
            return db.FirstOrDefault<DistrictItem>(query);
        }

        /// <summary>
        /// 根据区县编码获取区域对象
        /// </summary>
        /// <param name="districtCode">区县编码/param>
        /// <returns>区域对象</returns>
        private DistrictItem GetDistrict(string districtCode)
        {
            var db = UmbracoContext.Application.DatabaseContext.Database;
            var query = new Sql().Select("ProvinceCode, ProvinceName, CityCode, CityName, DistrictCode, DistrictName, AliasName")
                .From("[umbracoExtendingDistrict]")
                .Where("[DistrictCode] = @0", districtCode);
            return db.FirstOrDefault<DistrictItem>(query);
        }

        /// <summary>
        /// 解析地址的方法
        /// </summary>
        /// <param name="config">配置信息</param>
        /// <param name="address">地址</param>
        /// <param name="city">城市</param>
        /// <returns>返回解析结果</returns>
        private GeocoderItem GeocoderAddress(DealerConfiguration config, string address, string city)
        {
            IMaplatform map = null;
            switch (config.MapPlatform)
            {
                case "bd": map =  SafelyMapManager.GetPlatform(Platform.BAIDU, config.MapAppKey);break;
                case "qq": map= SafelyMapManager.GetPlatform(Platform.QQ, config.MapAppKey); break;
            }
            if (map != null)
            {   
                return map.Geocoder(address, city);
            }
            return null;
        }
    }
}
